home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / hard / drivr / BetaScan_1.12.lha / BetaScan / ScannerDev / MakeILBM.c < prev    next >
C/C++ Source or Header  |  1998-10-04  |  12KB  |  451 lines

  1. /************************************************************************/
  2. /*                                                                      */
  3. /* Write image as ilbm                                                  */
  4. /*                                                                      */
  5. /*                                                                      */
  6. /*                                                                      */
  7. /*                                                                      */
  8. /************************************************************************/
  9.  
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13.  
  14. #include <exec/types.h>
  15. #include <datatypes/pictureclass.h>
  16.  
  17. #include "MakeILBM.h"
  18. #include "packer.h"
  19.  
  20. #define ID_XBMI MAKE_ID('X','B','M','I')
  21. #define ILBM_BUFLEN 1500000
  22.  
  23. struct ImageBuf
  24. {
  25.   UBYTE* buf;
  26.   ULONG  actualLen;
  27.   FILE*  fh;
  28. };
  29.  
  30. struct ILBMFile
  31. {
  32.   char* fileName;
  33.   int   formLenOffset;
  34.   int   bodyLenOffset;
  35.   UBYTE flags;
  36.   
  37.   UBYTE depth;
  38.   UWORD width;
  39.   UWORD height;
  40.   UWORD xdpi;
  41.   UWORD ydpi;
  42.  
  43.   ULONG scanLineWidth;
  44.   ULONG bufLen;
  45.   struct ImageBuf buf[3];
  46. };
  47.  
  48. #define ILBMFLAGS_COMPRESS  (0x01 << 0)
  49. #define ILBMFLAGS_TEMPFILE  (0x01 << 1)
  50.  
  51. struct xbmi
  52. {
  53.   WORD xbmi_type;   /* ILBM_PAL, ILBM_RGB, ... (se below) */
  54.   WORD xbmi_xdpi;
  55.   WORD xbmi_ydpi;
  56. };
  57.  
  58.  
  59. #define ILBM_PAL        0       /* BODY data = indexes into the palette (CMAP)
  60.                                  * numcolors = 1<<depth;
  61.                                  */
  62.  
  63. #define ILBM_GREY       1       /* BODY =  grayscale values
  64.                                  * Bits per sample = number of bitplanes.
  65.                                  * Samples per pixel = 1.
  66.                                  * black = 0, white = (1<<depth)-1;
  67.                                  */
  68.  
  69. #define ILBM_RGB        2       /* BODY data = red, green, and blue values.
  70.                                  * Bits per sample = depth/3.
  71.                                  * Samples per pixel = 3.
  72.                                  */
  73.  
  74. #define ILBM_RGBA       3       /* BODY data = red, green, blue, and alpha
  75.                                  * channel values.
  76.                                  * Bits per sample = depth/4.
  77.                                  * Samples per pixel = 4.
  78.                                  */
  79.  
  80. #define ILBM_CMYK       4       /* BODY data = cyan, magenta, yellow, and black
  81.                                  * values.
  82.                                  * Bits per sample = depth/4.
  83.                                  * Samples per pixel = 4.
  84.                                  */
  85.  
  86. #define ILBM_CMYKA      5       /* BODY data = cyan, magenta, yellow, black,
  87.                                  * and alpha channel values.
  88.                                  * Bits per sample = depth/5.
  89.                                  * Samples per pixel = 5.
  90.                                  */
  91.  
  92. #define ILBM_BW         6       /* BODY data = black and white bits.
  93.                                  * Bits per sample = 1.
  94.                                  * Samples per pixel = 1.
  95.                                  * white = 0, black = 1.
  96.                                  */
  97.  
  98. static char* tempfile[3] = {"temp.red","temp.green","temp.blue"};
  99.  
  100. static void makePlane(UBYTE* source,UBYTE* dest,int bit,int length)
  101. {
  102.   int   bitNum,byteNum;
  103.   UBYTE b,sourceMask;
  104.  
  105.   sourceMask = 0x01 << bit;
  106.   
  107.   for( byteNum = 0 ; byteNum < length ; byteNum++ )
  108.   {
  109.     UBYTE destMask;
  110.     
  111.     destMask = 0x80;
  112.     b = 0;
  113.     for( bitNum = 0 ; bitNum < 8 ; bitNum++ )
  114.     {
  115.       if( (*source) & sourceMask )
  116.         b |= destMask;
  117.  
  118.       destMask >>= 1;
  119.       source++;
  120.     }
  121.     *(dest++) = b;
  122.   }
  123.  
  124. static void makeILBM(struct ILBMFile* ilbmfh)
  125. {
  126.   struct BitMapHeader BMHD;
  127.   struct xbmi         XBMI;
  128.   FILE*  fh;
  129.   int    c;
  130.   
  131.   if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  132.   {
  133.     for( c = 0 ; c < 3 ; c++ )
  134.     {
  135.       ilbmfh->buf[c].fh = fopen(tempfile[c],"r");
  136.       setvbuf(ilbmfh->buf[c].fh,ilbmfh->buf[c].buf,_IOFBF,ilbmfh->bufLen);
  137.     }
  138.   }
  139.   
  140.   BMHD.bmh_Width = ilbmfh->width;
  141.   BMHD.bmh_Height = ilbmfh->height;
  142.   BMHD.bmh_Left = 0;
  143.   BMHD.bmh_Top = 0;
  144.   BMHD.bmh_Depth = ilbmfh->depth;
  145.   BMHD.bmh_Masking = 0;
  146.   BMHD.bmh_Pad = 0;
  147.   BMHD.bmh_Transparent = 0;
  148.   BMHD.bmh_XAspect = 1;
  149.   BMHD.bmh_YAspect = 1;
  150.   BMHD.bmh_PageWidth = ilbmfh->width;
  151.   BMHD.bmh_PageHeight = ilbmfh->height;
  152.   
  153.   switch( ilbmfh->depth )
  154.   {
  155.     case 1:
  156.       XBMI.xbmi_type = ILBM_BW;
  157.       break;
  158.     case 8:
  159.       XBMI.xbmi_type = ILBM_GREY;
  160.       break;
  161.     case 24:
  162.       XBMI.xbmi_type = ILBM_RGB;
  163.       break;
  164.   }        
  165.   XBMI.xbmi_xdpi = ilbmfh->xdpi;
  166.   XBMI.xbmi_ydpi = ilbmfh->ydpi;
  167.  
  168.   if( fh = fopen(ilbmfh->fileName,"w") )
  169.   {
  170.     int scanLine,color,bitNum;
  171.     ULONG lineLen,bodyLen,formLen;
  172.     ULONG temp,psize;
  173.     UBYTE *line;
  174.     UBYTE *pline = NULL;
  175.     UBYTE *scanbuf = NULL;
  176.  
  177.     lineLen = ((ilbmfh->width+7)/8+1) & 0xFFFFFFFE;
  178.     line = malloc(lineLen);
  179.     if( (ilbmfh->flags & ILBMFLAGS_COMPRESS) && (pline = malloc(lineLen*2)) )
  180.       BMHD.bmh_Compression = 1;
  181.     else
  182.       BMHD.bmh_Compression = 0;
  183.       
  184.     temp = ID_FORM;
  185.     fwrite(&temp,4,1,fh);
  186.     ilbmfh->formLenOffset = ftell(fh);
  187.     temp = 0;
  188.     fwrite(&temp,4,1,fh);
  189.  
  190.     temp = ID_ILBM;
  191.     fwrite(&temp,4,1,fh);
  192.  
  193.     temp = ID_BMHD;
  194.     fwrite(&temp,4,1,fh);
  195.     temp = sizeof(struct BitMapHeader);
  196.     fwrite(&temp,4,1,fh);
  197.     fwrite(&BMHD,sizeof(struct BitMapHeader),1,fh);
  198.     
  199.     temp = ID_XBMI;
  200.     fwrite(&temp,4,1,fh);
  201.     temp = sizeof(struct xbmi);
  202.     
  203.     fwrite(&temp,4,1,fh);
  204.     fwrite(&XBMI,sizeof(struct xbmi),1,fh);
  205.  
  206.     if( ilbmfh->depth == 1 )
  207.     {
  208.       UBYTE b;
  209.       
  210.       temp = ID_CMAP;
  211.       fwrite(&temp,4,1,fh);
  212.       temp = 3*2;;
  213.       fwrite(&temp,4,1,fh);
  214.  
  215.       b = 0xFF;
  216.       fwrite(&b,1,1,fh);
  217.       fwrite(&b,1,1,fh);
  218.       fwrite(&b,1,1,fh);
  219.  
  220.       b = 0;
  221.       fwrite(&b,1,1,fh);
  222.       fwrite(&b,1,1,fh);
  223.       fwrite(&b,1,1,fh);
  224.     }
  225.     else if( ilbmfh->depth == 8 )
  226.     {
  227.       UBYTE b;
  228.       int   i;
  229.       
  230.       temp = ID_CMAP;
  231.       fwrite(&temp,4,1,fh);
  232.       temp = 3*256;;
  233.       fwrite(&temp,4,1,fh);
  234.       for( i = 0 ;  i < 256 ; i++ )
  235.       {
  236.         b = (UBYTE)i;
  237.         fwrite(&b,1,1,fh);
  238.         fwrite(&b,1,1,fh);
  239.         fwrite(&b,1,1,fh);
  240.       }
  241.     }
  242.     
  243.     temp = ID_BODY;
  244.     fwrite(&temp,4,1,fh);
  245.     ilbmfh->bodyLenOffset = ftell(fh);
  246.     temp = 0;
  247.     fwrite(&temp,4,1,fh);
  248.  
  249.     if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  250.       scanbuf = malloc(ilbmfh->scanLineWidth);
  251.     
  252.     switch( ilbmfh->depth )
  253.     {
  254.       case 1:
  255.         for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
  256.         {
  257.           if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  258.             fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[0].fh);
  259.           else
  260.             scanbuf = ilbmfh->buf[0].buf + scanLine*ilbmfh->scanLineWidth;
  261.  
  262.           if( pline == NULL )
  263.             fwrite(scanbuf,lineLen,1,fh);
  264.           else
  265.           {
  266.             psize = PackRow(scanbuf,pline,lineLen);
  267.             fwrite(pline,psize,1,fh);
  268.           }
  269.         }
  270.         break;
  271.       case 8:
  272.         for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
  273.         {
  274.           if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  275.             fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[0].fh);
  276.           else
  277.             scanbuf = ilbmfh->buf[0].buf + scanLine*ilbmfh->scanLineWidth;
  278.           for( bitNum = 0 ; bitNum < 8 ; bitNum++ )
  279.           {
  280.             makePlane(scanbuf,line,bitNum,lineLen);
  281.             if( pline == NULL )
  282.               fwrite(line,lineLen,1,fh);
  283.             else
  284.             {
  285.               psize = PackRow(line,pline,lineLen);
  286.               fwrite(pline,psize,1,fh);
  287.             }
  288.           }
  289.         }
  290.         break;
  291.       case 24:
  292.         for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
  293.         {
  294.           for( color = 0 ; color < 3 ; color++ )
  295.           {
  296.             if( ilbmfh->buf[color].buf )
  297.             {
  298.               if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  299.                 fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[color].fh);
  300.               else
  301.                 scanbuf = ilbmfh->buf[color].buf + scanLine*ilbmfh->scanLineWid